home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / GoldED Tools / GoldDock / ARexx / ARx_Help.ged < prev    next >
Encoding:
Text File  |  1996-09-27  |  19.7 KB  |  536 lines

  1. /** $VER: ARx_Help.ed 2.0 (28 Feb 1994)
  2.  ** by Robin Evans
  3.  **
  4.  ** Modifications for GoldED done by Markus Aretz ( 9  May 1994)
  5.  **
  6.  ** Display the ARexxGuide page for the word currently under the cursor.
  7.  ** Will call ARx_Setup.rexx if env: variables are not set.
  8.  **
  9.  ** Add the following line to the file S:Ed-Startup or whatever other file
  10.  ** you use to set Ed's default configuration.
  11.  **
  12.  **     sf 1 "rx \arx_help\"
  13.  **
  14.  **     This will hook ARexxGuide into the F1 key. Consult a manual for
  15.  **     other possible key assignments. The same command can also be issued
  16.  **     from within an Ed session to make a temporary assignment. Just type
  17.  **     in the command at a `*' prompt after pressing the <Esc> key. (Those
  18.  **     who have been reading Denny Atkin's DOS column in AmigaWorld have
  19.  **     learned that Ed has a far more comprehensive menu if the menu items
  20.  **     in the Ed-Startup file are deleted.)
  21.  **
  22.  **  Environmental variables:
  23.  **      env:AmigaGuide/path must include the directory where
  24.  **          arx_guide.xref is located.
  25.  **      env:ARexxGuide/AGCmd must hold the name of the command
  26.  **          (probably something like `sys:utilities/Multiview') used to
  27.  **          show launch amigaguide files.
  28.  **      env:ARexxGuide/ShowFullHelp must be set to 1 if the rexxarplib
  29.  **          information window is to be shown. rexxarplib.library is
  30.  **          required for that feature only.
  31.  **
  32.  ** See `Tutorials: Help key macros' ( HELPKEYMACRO ) in ARexxGuide for more
  33.  ** information about this macro.
  34.  **/
  35.  
  36. signal on syntax
  37. signal on break_c
  38. signal on halt
  39. signal on failure
  40.  
  41. options results
  42. parse arg LkUp
  43.  
  44. /* TRACE R */
  45.  
  46. if ~show('L','amigaguide.library') then
  47.     call addlib('amigaguide.library',-1,-30)
  48.  
  49. if ~show('L','rexxsupport.library') then
  50.     call addlib('rexxsupport.library',0,-30)
  51.  
  52. TRUE=1; FALSE=0
  53.  
  54.    /* Load the cross-ref file. Function returns quickly if the file is  **
  55.    ** already loaded, but -- like ADDLIB() it can return true even if   **
  56.    ** the file isn't available, so we check by looking for a known node.*/
  57. call DisplayStatus('ARx_Help: Checking .xref files...')
  58. call LoadXref('ARx_Guide.xref')
  59. do Attempt = 1
  60.    if getxref('TRACEOPT1') = 10 then do   /* Leave below */
  61.       /* Did this in a loop just to be able to use signal for a no-load */
  62.       if Attempt = 2 then
  63.          signal XRefError
  64.       else if 'ARx_Setup.rexx'('HELP',,address()) ~= 0 then signal XRefError
  65.          /* It didn't load, so get rid of anything in mem and try again */
  66.       address command 'expungexref'
  67.    end
  68.    else leave Attempt
  69. end
  70.  
  71. /* Add any extra files included in the env: variable.                */
  72. ExtraXRef = GetEnv('ARexxGuide/XRFiles')
  73. do i = 1 for words(ExtraXRef)
  74.       /* 'Call' because we don't care about errors here.             */
  75.    call loadxref(word(ExtraXRef, i))
  76. end
  77.  
  78. call DisplayStatus('ARexxGuide online help system...')
  79.  
  80.    /* It isn't used in the setup provided here, but it's possible to    **
  81.    ** just pass a word as an argument to this routine and get a lookup  **
  82.    ** on that.                                                          */
  83. if LkUp = '' then do
  84.       /* Get the current line and position. Editor's commands are all   **
  85.       ** in subroutines and not in the main code.                       */
  86.    HLine = GetCLine()
  87.    CurPos = GetCurPos()
  88.       /* Show the index requester if it's a blank line */
  89.    if HLine = '' | verify(HLine, ' ;') = 0 then do
  90.       call ShowInfo(,, CurPos, Kwd)
  91.       signal CleanExit
  92.    end
  93.  
  94.       /* Cut a single clause out of preceding clauses                   */
  95.    SemPos = lastpos(';', HLine, CurPos) + 1
  96.       /* This will break if a semicolon is used within a string         **
  97.       ** but checking for that seems like overkill.                     */
  98.    if SemPos > 1 then do
  99.       if SemPos < CurPos + 1 then do
  100.          parse var HLine =SemPos HLine ';'
  101.          CurPos = CurPos - SemPos + 1
  102.       end
  103.    end
  104.       /* Cut it out of following clauses                                 */
  105.    else
  106.       parse var HLine HLine ';'
  107.  
  108.    /* The current keyword is used within MChar select clause             */
  109.    Kwd = upper(word(HLine, 1))
  110.  
  111.                                               /* Hex characters: SpTbRt    */
  112.       /* Check for special characters -- operators, quotation marks, etc */
  113.    MChar = pos(substr(HLine,CurPos,1), '+-/*%|&^><=,;:~)("''?!.'||'20090a'x)
  114.    select
  115.       when MChar = 0 then do     /* It isn't one of the chars */
  116.          /* Look for whole word if it isn't a special character */
  117.          LkUp = GetCWord(HLine, CurPos)
  118.       end
  119.       when MChar <= 5 then
  120.          select
  121.             when MChar <= 2 then       /* + or - */
  122.                if Kwd = 'PARSE' then
  123.                   LkUp = 'PARSETMP5'
  124.                else
  125.                   LkUp = 'ARITHMETIC'
  126.             when MChar <= 4 then do    /* / or * */
  127.                   /* This picks up the three characters surrounding a '*' or '/' */
  128.                ComChar = substr(HLine, max(1, CurPos - 1), 3)
  129.                if pos('/*', ComChar) + pos('*/', ComChar) > 0 then
  130.                   LkUp = 'COMMENT'
  131.                else
  132.                   LkUp = 'ARITHMETIC'
  133.             end
  134.             otherwise
  135.                LkUp = 'ARITHMETIC'        /* % */
  136.          end
  137.       when MChar <= 13 then
  138.          select
  139.             when MChar <= 8 then do    /* | or & or ^ */
  140.                   /* This picks up the three characters surrounding token */
  141.                ComChar = substr(HLine, max(1, CurPos - 1), 3)
  142.                if pos('||', ComChar) > 0 then
  143.                   LkUp = 'CONCATENATION'
  144.                else
  145.                   LkUp = 'LOGICAL'
  146.             end
  147.             when MChar <= 10 then    /* < or > */
  148.                LkUp = 'COMPARISON'
  149.             when MChar = 11 then    /* = */
  150.                if Kwd = 'PARSE' then
  151.                   LkUp = 'PARSETMP5'
  152.                else if symbol(strip(left(HLine, max(1, CurPos-1)))) == 'BAD' then
  153.                   LkUp = 'COMPARISON'
  154.                else
  155.                   LkUp = 'ASSIGNMENT'
  156.             when MChar = 12 then    /* , */
  157.                LkUp = 'COMMA'
  158.             otherwise               /* ; */
  159.                LkUp = 'SEMICOLON'
  160.          end
  161.       when MChar <= 19 then
  162.          select
  163.             when MChar = 14 then    /* : */
  164.                LkUp = 'LABEL'
  165.             when MChar = 15 then do /* ~ */
  166.                   /* is the next character a comparison operator? */
  167.                if pos(substr(HLine, CurPos , 2), '~=~>~<') > 0 then
  168.                   LkUp = 'COMPARISON'
  169.                else
  170.                   LkUp = 'LOGICAL'
  171.             end
  172.             when MChar <=17 then    /* ) or ( */
  173.                if Kwd = 'PARSE' then
  174.                   LkUp = 'PARSETMP5'
  175.                else
  176.                   LkUp = 'PAREN'
  177.             otherwise               /* " or ' */
  178.                LkUp = 'STRING'
  179.          end
  180.       otherwise
  181.          select
  182.             when MChar = 20 then    /* ? */
  183.                if Kwd = 'TRACE' then
  184.                   LkUp = 'TRACEOPT1'
  185.                else
  186.                   LkUp = '?'
  187.             when MChar = 21 then    /* ! */
  188.                if Kwd = 'TRACE' then
  189.                   LkUp = 'TRACEOPT2'
  190.                else
  191.                   LkUp = '!'
  192.             when MChar = 22 then do   /* . -- dot  */
  193.                   /* Get the surrounding ARexx token */
  194.                StPos = verify(' 'HLine, '+-|/&=~\><^,;:()"'' ', 'M', lastpos(' ', ' 'HLine, CurPos))
  195.                Token = substr(HLine, StPos, verify(HLine' ', '+-|/&=~\><^,;:()"'' ', M, CurPos) - StPos)
  196.                select
  197.                   when Token = '.' then
  198.                      if Kwd = 'PARSE' then
  199.                         LkUp = 'PARSETMP2'
  200.                      else
  201.                         LkUp = Token
  202.                   when datatype(Token, 'N') then
  203.                      LkUp = 'NUMBER'
  204.                   when datatype(Token, 'S') then
  205.                      if datatype(left(Token,1),'M') | verify(Token, '!@#$', 'M') = 1
  206.                         then LkUp = 'COMPVAR'
  207.                   otherwise
  208.                      LkUp = Token
  209.                end
  210.             end
  211.             otherwise               /* At a space or EOL */
  212.                if CurPos >= wordindex(HLine, 1) then
  213.                   LkUp = GetCWord(HLine, CurPos)
  214.                else do
  215.                   call ShowInfo(HLine,, CurPos, Kwd)
  216.                   signal CleanExit
  217.                end
  218.          end
  219.    end
  220.  
  221.  
  222.    /* Check for special words like `command' in `address command'       **
  223.    ** and most of the subkeywords in instructions like DO.              */
  224.    if word(HLine, 1) ~= LkUp then do CheckOpt = 1 for 1  /* Let's us leave */
  225.       if GetXRef(LkUp) = 10 | find('ARG PULL UPPER COMMAND', upper(LkUp)) > 0 then do
  226.          if word(GetXRef(Kwd),3) = 2 then select
  227.             when Kwd = 'DO' then do
  228.                SpecWord = find('UNTIL WHILE TO FOR BY FOREVER ', upper(LkUp))
  229.                if SpecWord > 0 then
  230.                   LkUp = word('DOOPT4 DOOPT4 DOOPT2 DOOPT3 DOOPT2 DOOPT5', SpecWord)
  231.             end
  232.             when Kwd = 'PARSE' then do
  233.                SpecWord = find('ARG PULL EXTERNAL NUMERIC SOURCE VERSION VALUE VAR WITH', upper(LkUp))
  234.                if SpecWord > 0 then do
  235.                   LkUp = 'PARSESRC'SpecWord
  236.                   if SpecWord = 9 then
  237.                      LkUp = 'PARSESRC7'
  238.                end
  239.                else
  240.                   LkUp = 'PARSETMP1'
  241.             end
  242.             when Kwd = 'OPTIONS' then
  243.                if find('RESULTS PROMPT FAILAT CASHE ON OFF', upper(LkUp)) > 0 then
  244.                   LkUp = Kwd
  245.             when Kwd = 'TRACE' then
  246.                if verify(upper(right(LkUp,1)), 'IRACLENOBS') = 0 then
  247.                   LkUp = 'TRACEOPT'
  248.             when Kwd = 'SIGNAL' then
  249.                if find('ON OFF', upper(LkUp)) >0 then
  250.                   LkUp = 'SIGTRAP'
  251.                else if pos('BREAK_', upper(LkUp)) = 1 then
  252.                   LkUp = 'BREAK_'
  253.                else
  254.                   LkUp = 'SIGTRAN'
  255.             when upper(LkUp) = 'UPPER' then
  256.                if Kwd ~= 'UPPER' then
  257.                   LkUp = 'UPPER()'
  258.             when Kwd = 'ADDRESS' then
  259.                if abbrev(word(HLine, 2), LkUp) then do
  260.                   LkUp = Kwd
  261.                   leave CheckOpt  /* so we don't get address() */
  262.                end
  263.             otherwise
  264.          end
  265.          if GetXRef(LkUp'()') ~= 10 then
  266.             LkUp = LkUp'()'
  267.       end
  268.    end
  269. end
  270. else do     /* Word was supplied as argument to the script */
  271.    upper LkUp
  272.    CurPos = 1; HLine = LkUp
  273. end
  274.  
  275. XRVal = upper(GetXRef(LkUp))
  276. if find('10 NODE/K', XRVal) > 0 then do
  277.    if ShowInfo( HLine, LkUp, CurPos, Kwd ) = 0 then signal CleanExit
  278.    else XRVal = upper(GetXRef(LkUp))
  279. end
  280.  
  281. if ~abbrev(word(XRVal,2), '"ARX_') then
  282.    Src = 'Other ref:'
  283. else
  284.    Src = 'ARexxGuide:'
  285. call DisplayStatus(Src upper(LkUp) '['word('Explanation Function Instruction', word(getxref(LkUp), 3)+1)']')
  286.  
  287. signal on error
  288. call DisplayAG(LkUp)
  289. signal off error
  290.  
  291. CleanExit:
  292.         /* Since it can cause severe problems, it's removed when not needed */
  293. call remlib('amigaguide.library')
  294. call EditorExit()
  295. exit 0
  296.  
  297. /*************************************************************************
  298. ** Error routines.                                                      */
  299.  
  300. XRefError:
  301.    ErrMsg = 'Unable to load the cross-reference file ARx_Guide.xref\'
  302.    if ~exists('env:amigaguide/path') then
  303.       ErrMsg = ErrMsg || 'Your environmental variable "amigaguide/path" is not set.\'
  304.    else
  305.       ErrMsg = ErrMsg '  Be sure to include that file''s directory in env:amigaguide/path.\'
  306.    ErrMsg = ErrMsg '  The .xref file may be put into the current directory or into\',
  307.    '  any directory included in the amigaguide/path environmental variable.'
  308.    call PutErrMsg(SIGL, ErrMsg)
  309.    exit 6
  310. NoCmd:
  311.    call PutErrMsg(SIGL, 'Can''t read environmental variable "env:arexxguide/AGcmd".\',
  312.              '  That variable must hold the name of the command you use\',
  313.              '  to show AmigaGuide files.')
  314.    exit 7
  315. Syntax:
  316.    call PutErrMsg(SIGL, '   Syntax error #'rc ':' errortext(rc))
  317.    exit 9
  318. Failure:
  319.    call PutErrMsg(SIGL, '   Command "'sourceline(SIGL)'" failed.')
  320.    exit 10
  321. Halt:
  322. Break_C:
  323.    call PutErrMsg(SIGL, '   Execution halted.')
  324.    exit 8
  325. Error:
  326.    call PutErrMsg(SIGL, '   Command error in display routine: RC =' rc'.\\',
  327.              '  The name of your AmigaGuide viewer may not be properly set, or\',
  328.              '  an .xref file might have been loaded for a database not located\',
  329.              '  in one of the directories in env:AmigaGuide/path.\',
  330.              '  Type rx ARx_Setup at a shell prompt to run the setup program again.')
  331.    exit 9
  332. PutErrMsg:
  333.    call trace b
  334.    ErrMsg ='Sorry an enexpected error has occurred in line' arg(1)'.\\'arg(2)
  335.    signal off syntax
  336.    signal off halt
  337.    signal off break_c
  338.    WinHi = 59 + CountChar('\', ErrMsg) * 11
  339.    call DisplayStatus('ARx_Help macro error.')
  340.    if open(6ErrWin, 'raw:0/0/640/'WinHi'/Arx_Help Error/SCREEN *') then do
  341.       call writeln(6ErrWin, translate(ErrMsg,'0a'x, '\'))
  342.       call writech(6ErrWin, '0a'x'        -- Press any key -- ')
  343.       call readch(6ErrWin)
  344.    end
  345.    call EditorExit()
  346.    return 0
  347.  
  348. exit 0
  349.  
  350. /*************************************************************************
  351. ** General utility routines                                             */
  352.  
  353. GetAGCmd: procedure
  354.       /* Calls the setup program if env:ARexxGuide/AGCmd is not set       */
  355.    AGCmd = GetEnv('ARexxGuide/AGCmd')
  356.    if AGCmd = '' then do
  357.       call DisplayStatus('Please wait... Running setup routine')
  358.       if 'ARx_Setup.rexx'('HELP',,address()) ~= 0 then
  359.          signal NoCmd
  360.       else
  361.          AGCmd = GetEnv('ARexxGuide/AGCmd')
  362.    end
  363.    return AGCmd
  364.  
  365. ShowInfo:
  366.       /* The env: var ShowFullHelp determines whether a simple editor     **
  367.       ** requester is used, or a complex rexxarplib window that displays  **
  368.       ** far more information about the current line, but is also slow.   */
  369.    if getenv('ARexxGuide/ShowFullHelp') ~= '1' then do
  370.       if BoolReq(upper(LkUp) 'not found.','Show ARexxGuide index?') then do
  371.          LkUp = 'ARx_NdxCont'
  372.          return 1
  373.       end
  374.       else
  375.          return 0
  376.    end
  377.    else do
  378.          /* Show that we're doing something */
  379.       call DisplayStatus(LkUp 'not found. Checking clause...')
  380.  
  381.          /* The .rexx part of the name has to be added because the default **
  382.          ** extension is set by editor: .TTX, .edge, etc. Since this       **
  383.          ** is set up for different editors, it's stored with the generic  **
  384.          ** extension.                                                     */
  385.       return 'ARx_RArpInfoWin.rexx'(HLine,LkUp,CurPos,Kwd,SetAddress(),SetExecStr(),GetWinInfo())
  386.    end
  387.  
  388. CountChar:
  389.    return length(arg(2)) - length(compress(arg(2), arg(1)))
  390.  
  391. GetEnv: procedure
  392.       /* Arguments:                                                     **
  393.       **   arg(1) := The name of the variable to retrieve               **
  394.       ** Returns     a string                                           */
  395.  
  396.       /* Use external function of same name if it's available           */
  397.    if show('L', 'rexxarplib.library') then
  398.       return 'GetEnv'(arg(1))
  399.       /*  OPEN()  will fail if variable is not defined. Null will be    **
  400.       ** returned in that case                                          */
  401.    if open(6Env, 'env:'arg(1), 'R') then do
  402.       EnvVar = readln(6Env)
  403.       call close 6Env
  404.    end
  405.    else EnvVar = ''
  406.    return EnvVar
  407.  
  408. Tab2Space:  procedure
  409.    parse arg TSize, Line
  410.    tpos=pos('09'x,Line);
  411.    do while tpos>0;
  412.       Line=insert('',Line, tpos, min(1, tpos//TSize)*(TSize-tpos//TSize));
  413.       tpos=pos('09'x, Line,tpos+1);
  414.    end;
  415. return translate(Line,' ','09'x)
  416.  
  417.  
  418. /***********************************************************************
  419. ** Editor-specific commands.                                          **
  420. **    These function calls are used elsewhere to make it easier to    **
  421. **    use the same script for different editors.                      */
  422.  
  423.  
  424. GetCLine: procedure
  425.    'QUERY BUFFER VAR LINE'
  426.    return LINE
  427.  
  428. GetCurPos: procedure
  429.    'QUERY COLUMN VAR COL'
  430.    return COL
  431.  
  432. GetCWord:  procedure
  433.       /* Send back current word */
  434.    parse arg Line, CPos
  435.       /* list of valid word-separator charaters: space, operator, spec char */
  436.    SepChar = ' +-*/%|&~=><^,;:()."''\'
  437.       /* Back up in line if Current position is not an alpha character  or digit */
  438.    do while (verify(substr(Line,CPos,1), SepChar || '0a'x) = 0) & (CPos > 1)
  439.       CPos = CPos - 1
  440.    end
  441.       /* Cut off word at space _or_ any of the operator or special characters     */
  442.    Word = reverse(left(Line,verify(Line' ',SepChar,'M',CPos) - 1))
  443.    return reverse(left(Word,verify(Word' ',SepChar,'M', max(1,length(Word) + 1 - CPos))-1))
  444.  
  445. DisplayStatus:
  446.       /* Put message in title bar of editor */
  447.   'REQUEST STATUS="'arg(1)'"'
  448.    return 0
  449.  
  450. BoolReq: procedure
  451.       /* Present a Yes/No requester                                      **
  452.       ** Arguments:                                                      **
  453.       **    arg(1)   := Titlebar text                                    **
  454.       **    arg(2)   := Message in body of requester                     */
  455.    'REQUEST TITLE "'center(arg(1),37)'" BODY "'center(arg(2),37)'" BUTTON "_Yes|_No"'
  456.    
  457.    return result
  458.  
  459. GetWinInfo:
  460.       /* Return Information about window                                 **
  461.       **    Format of returned value:                                    **
  462.       **           word 1 = x position                                   **
  463.       **           word 2 - y position                                   **
  464.       **           word 3 = name of public screen                        */
  465.    /* Can't get window info for ed.                                      */
  466.    'QUERY X VAR WINX'
  467.    'QUERY Y VAR WINY'
  468.    'QUERY SCREEN VAR WINNAME'
  469.  
  470.    return WINX WINY WINNAME
  471.  
  472. EditorExit:
  473.       /* Used for any editor-specific commands that should be issued on  **
  474.       ** exit.                                                           */
  475.    return 0
  476.  
  477. SetExecStr:
  478.       /* The string returned by this function is used in the rexxarplib  **
  479.       ** window to send link commands to AmigaGuide.                     */
  480.    AGCmd = GetEnv('arexxguide/agcmd')
  481.    if AGCmd = '' then do
  482.       NoCmd_Return = 'ReShowInfo'
  483.       signal NoCmd
  484.    end
  485.    if ~abbrev(AGCmd, 'Multi') then
  486.       return 'address ARX_ARP quit; if ~show(P, ARX_GUIDE) then do;address command; ''run >nil:' AGCmd 'ARexxGuide.guide portname ARX_GUIDE'';waitforport ARX_GUIDE; end; address ARX_GUIDE; windowtofront; link'
  487.    else
  488.       return 'address ARX_ARP quit; address command; ''run >nil: ' AGCmd 'document'
  489.  
  490. SetAddress:
  491.       /* Address used as target of the commands from rarp window         */
  492.    return 'ARX_HELP'
  493.  
  494. DisplayAG:
  495.       /* Show the node in AmigaGuide viewer. Missing env: will call      **
  496.       ** error handler which runs the setup prg. and then passes         **
  497.       ** control back to here.                                           */
  498.    arg LkUp
  499.    AGCmd = GetEnv('arexxguide/agcmd')
  500.    if AGCmd = '' then do
  501.       NoCmd_Return = 'ShowFunc'
  502.       signal NoCmd
  503.    end
  504.  
  505.  
  506.    if abbrev(AGCmd, 'Multi') then
  507.       PrtOpt = ''
  508.    else
  509.       PrtOpt = 'portname ARX_GUIDE'
  510.  
  511.       /* See if our AG window is open */
  512.    if ~show('P','ARX_GUIDE') then do
  513.       if pos('/', LkUp) > 0 then
  514.          parse var LkUp DB '/' Doc
  515.       else
  516.          DB = ''
  517.       address command 'run' AGCmd DB 'document' LkUp PrtOpt 'requester'
  518.       if rc > 5 then do
  519.          NoCmd_Return = 'ShowFunc'
  520.          signal NoCmd
  521.       end
  522.  
  523.    end
  524.    else do
  525.          /* show the node */
  526.       address ARX_GUIDE 'Link' LkUp
  527.       address ARX_GUIDE 'unzoomwindow'
  528.       address ARX_GUIDE 'windowtofront'
  529.          /* This will be called only if rexxarplib is available and will **
  530.          ** try to bring a public screen to the foreground. OK if there  **
  531.          ** isn't a screen of that name available.                       */
  532.       if show('L', 'rexxarplib.library') then
  533.          call screentofront('ARX_GUIDE')
  534.    end
  535. return 0
  536.